﻿using System;
using SoftwareConsulting.BI11.NumericalMethods.Interfaces;

namespace SoftwareConsulting.BI11.NumericalMethods.Iterations
{
    /// <summary>
    /// Класс поиска нуля половинным делением
    /// </summary>
    public class BisectionZeroFinder : FunctionalIterator
    {	   
        private double _xNegative;//аргумент, при котором значение функции отрицательное	    
        private double _xPositive;//аргумент, при котором значение функции положительное

        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="function"></param>
        public BisectionZeroFinder(IOneVariableFunction function) : 
            base(function)
        {
        }

        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="function"></param>
        /// <param name="xNegative">аргумент, при котором значение функции отрицательное</param>
        /// <param name="xPositive">аргумент, при котором значение функции положительное</param>
        public BisectionZeroFinder(IOneVariableFunction function, double xNegative, double xPositive)
											: this(function)
        {
            SetXNegative(xNegative);
            SetXPositive(xPositive);
        }

        /// <summary>
        /// Выполняет итерацию
        /// </summary>
        /// <returns></returns>
        public override double DoIteration()
        {
            SetBestZeroApproximation((_xPositive + _xNegative) * 0.5);
            if (Function.GetValue(BestZeroApproximation) > 0)
                _xPositive = BestZeroApproximation;
            else
                _xNegative = BestZeroApproximation;
            return GetRelativeError(Math.Abs(_xPositive - _xNegative));
        }

        /// <summary>
        /// Возвращает аргумент, при котором значение функции отрицательное
        /// </summary>
        public double XNegative
        {
            get
            {
                return _xNegative;
            }
        }

        /// <summary>
        /// Устанавливает аргумент, при котором значение функции отрицательное
        /// </summary>
        public void SetXNegative(double xNegative)            
        {
            if (Function.GetValue(xNegative) > 0)
                throw new ArgumentException("xNegative");
            _xNegative = xNegative;
        }

        /// <summary>
        /// Возвращает аргумент, при котором значение функции положительное
        /// </summary>
        public double XPositive
        {
            get
            {
                return _xPositive;
            }
        }

        /// <summary>
        /// Устанавливает аргумент, при котором значение функции положительное
        /// </summary>
        public void SetXPositive(double xPositive)
        {
            if (Function.GetValue(xPositive) < 0)
                throw new ArgumentException("xPositive");
            _xPositive = xPositive;
        }
    }
}
